using System;
using System.Collections.Generic;
using System.Text;

namespace RapidHDL
{
    public class TestALUBlock : RapidHardware
    {
        public override bool ConfigureSettings()
        {
            Settings.UseStart = false;
            Settings.BuildHardware = true;
            Settings.ForceBuildHardware = false;
            Settings.RunFromXilinx = true;
            Settings.ClockFrequency = 1;
            Settings.UseSDRAM = true;
            Settings.BuildRemote = false;
            return true;
        }

        public override bool GenerateStructure(TopLevelComponent TopLevelComponent)
        {
            TopLevelComponent.TestBusWrite.Join(0);

            NodeVector nvA = new NodeVector(TopLevelComponent, "A", 3);
            NodeVector nvB = new NodeVector(TopLevelComponent, "B", 3);
            NodeVector nvC = new NodeVector(TopLevelComponent, "C", 1);
            SystemInterface.AddSignalSource("A", nvA, 0);
            SystemInterface.AddSignalSource("B",nvB,0);
            SystemInterface.AddSignalSource("C", nvC, 0);

            NodeVector nvAddOut = new NodeVector(TopLevelComponent, "add_out", 4);
            ALUComponent oAdd = new ALUComponent(TopLevelComponent, "add", ALUType.Add, 3);
            oAdd.I_A.Join(nvA);
            oAdd.I_B.Join(nvB);
            oAdd.O_A.Join(nvAddOut);

            NodeVector nvinvOut = new NodeVector(TopLevelComponent, "inv_out", 4);
            ALUComponent oinv = new ALUComponent(TopLevelComponent, "inv", ALUType.Inv, 3);
            oinv.I_A.Join(nvA);
            oinv.O_A.Join(nvinvOut);

            NodeVector nvtwosOut = new NodeVector(TopLevelComponent, "twos_out", 4);
            ALUComponent otwos = new ALUComponent(TopLevelComponent, "twos", ALUType.TwoComplement, 3);
            otwos.I_A.Join(nvA);
            //otwos.I_B.Join(nvB);
            otwos.O_A.Join(nvtwosOut);

            NodeVector nvAndMaskOut = new NodeVector(TopLevelComponent, "AndMask_out", 3);
            ALUComponent oAndMask = new ALUComponent(TopLevelComponent, "AndMask", ALUType.AndMask, 3);
            oAndMask.I_A.Join(nvA);
            oAndMask.I_B.Join(nvB);
            oAndMask.O_A.Join(nvAndMaskOut);

            NodeVector nvOrMaskOut = new NodeVector(TopLevelComponent, "OrMask_out", 3);
            ALUComponent oOrMask = new ALUComponent(TopLevelComponent, "OrMask", ALUType.OrMask, 3);
            oOrMask.I_A.Join(nvA);
            oOrMask.I_B.Join(nvB);
            oOrMask.O_A.Join(nvOrMaskOut);

            NodeVector nvXorMaskOut = new NodeVector(TopLevelComponent, "XorMask_out", 3);
            ALUComponent oXorMask = new ALUComponent(TopLevelComponent, "XorMask", ALUType.XorMask, 3);
            oXorMask.I_A.Join(nvA);
            oXorMask.I_B.Join(nvB);
            oXorMask.O_A.Join(nvXorMaskOut);

            NodeVector nvCompareGreaterOut = new NodeVector(TopLevelComponent, "CompareGreater_out", 1);
            ALUComponent oCompareGreater = new ALUComponent(TopLevelComponent, "CompareGreater", ALUType.CompareGreater, 3);
            oCompareGreater.I_A.Join(nvA);
            oCompareGreater.I_B.Join(nvB);
            oCompareGreater.O_A.Join(nvCompareGreaterOut);

            NodeVector nvCompareEqualOut = new NodeVector(TopLevelComponent, "CompareEqual_out", 1);
            ALUComponent oCompareEqual = new ALUComponent(TopLevelComponent, "CompareEqual", ALUType.CompareEqual, 3);
            oCompareEqual.I_A.Join(nvA);
            oCompareEqual.I_B.Join(nvB);
            oCompareEqual.O_A.Join(nvCompareEqualOut);
             

            NodeVector nvSubtractOut = new NodeVector(TopLevelComponent, "Subtract_out", 4);
            ALUComponent oSubtract = new ALUComponent(TopLevelComponent, "Subtract", ALUType.Subtract, 3);
            oSubtract.I_A.Join(nvA);
            oSubtract.I_B.Join(nvB);
            oSubtract.O_A.Join(nvSubtractOut);

            NodeVector nvAddSubOut = new NodeVector(TopLevelComponent, "AddSub_out", 4);
            ALUComponent oAddSub = new ALUComponent(TopLevelComponent, "AddSub", ALUType.AddSub, 3);
            //
            oAddSub.I_A.Join(nvA);
            oAddSub.I_B.Join(nvB);
            oAddSub.I_Subtract.Join(nvC);
            oAddSub.O_A.Join(nvAddSubOut);

            
            NodeVector nvShiftRigthArithOut = new NodeVector(TopLevelComponent, "ShiftRigthArith_out", 3);
            ALUComponent oShiftRigthArith = new ALUComponent(TopLevelComponent, "ShiftRigthArith", ALUType.ShiftRightArith, 3);
            oShiftRigthArith.I_A.Join(nvA);
            oShiftRigthArith.O_A.Join(nvShiftRigthArithOut);

            NodeVector nvShiftLeftArithOut = new NodeVector(TopLevelComponent, "ShiftLeftArith_out", 3);
            ALUComponent oShiftLeftArith = new ALUComponent(TopLevelComponent, "ShiftLeftArith", ALUType.ShiftLeftArith, 3);
            oShiftLeftArith.I_A.Join(nvA);
            oShiftLeftArith.O_A.Join(nvShiftLeftArithOut);

            NodeVector nvShiftRightLogicalOut = new NodeVector(TopLevelComponent, "ShiftRightLogical_out", 3);
            ALUComponent oShiftRightLogical = new ALUComponent(TopLevelComponent, "ShiftRightLogical", ALUType.ShiftRightLogical, 3);
            oShiftRightLogical.I_A.Join(nvA);
            oShiftRightLogical.O_A.Join(nvShiftRightLogicalOut);

            NodeVector nvShiftLeftLogicalOut = new NodeVector(TopLevelComponent, "ShiftLeftLogical_out", 3);
            ALUComponent oShiftLeftLogical = new ALUComponent(TopLevelComponent, "ShiftLeftLogical", ALUType.ShiftLeftLogical, 3);
            oShiftLeftLogical.I_A.Join(nvA);
            oShiftLeftLogical.O_A.Join(nvShiftLeftLogicalOut);


            NodeVector nvShiftRightRotateOut = new NodeVector(TopLevelComponent, "ShiftRightRotate_out", 3);
            ALUComponent oShiftRightRotate = new ALUComponent(TopLevelComponent, "ShiftRightRotate", ALUType.ShiftRightRotate, 3);
            oShiftRightRotate.I_A.Join(nvA);
            oShiftRightRotate.O_A.Join(nvShiftRightRotateOut);

            NodeVector nvShiftLeftRotateOut = new NodeVector(TopLevelComponent, "ShiftLeftRotate_out", 3);
            ALUComponent oShiftLeftRotate = new ALUComponent(TopLevelComponent, "ShiftLeftRotate", ALUType.ShiftLeftRotate, 3);
            oShiftLeftRotate.I_A.Join(nvA);
            oShiftLeftRotate.O_A.Join(nvShiftLeftRotateOut);

            NodeVector nvIncOut = new NodeVector(TopLevelComponent, "Inc_out", 4);
            ALUComponent oInc = new ALUComponent(TopLevelComponent, "Inc", ALUType.Inc, 3);
            oInc.I_A.Join(nvA);
            oInc.O_A.Join(nvIncOut);

            NodeVector nvDecOut = new NodeVector(TopLevelComponent, "Dec_out", 4);
            ALUComponent oDec = new ALUComponent(TopLevelComponent, "Dec", ALUType.Dec, 3);
            oDec.I_A.Join(nvA);
            oDec.O_A.Join(nvDecOut);

            return true;
        }

        public override bool ConfigureSignalViews(TopLevelComponent TopLevelComponent)
        {
            SystemInterface.AddSignalView(".add_out");
            SystemInterface.AddSignalView(".inv_out");
            SystemInterface.AddSignalView(".twos_out");
            SystemInterface.AddSignalView(".AndMask_out");
            SystemInterface.AddSignalView(".OrMask_out");
            SystemInterface.AddSignalView(".XorMask_out");
          
            SystemInterface.AddSignalView(".CompareGreater_out");
            SystemInterface.AddSignalView(".CompareEqual_out");
           
            SystemInterface.AddSignalView(".Subtract_out");
            SystemInterface.AddSignalView(".AddSub_out");            
            SystemInterface.AddSignalView(".ShiftRigthArith_out");
            SystemInterface.AddSignalView(".ShiftLeftArith_out");
            SystemInterface.AddSignalView(".ShiftRightLogical_out");
            SystemInterface.AddSignalView(".ShiftLeftLogical_out");
            SystemInterface.AddSignalView(".ShiftRightLogical_out");
            SystemInterface.AddSignalView(".ShiftRightRotate_out");
            SystemInterface.AddSignalView(".ShiftLeftRotate_out");
            SystemInterface.AddSignalView(".ShiftLeftLogical_out");
            SystemInterface.AddSignalView(".Inc_out");
            SystemInterface.AddSignalView(".Dec_out"); 

            return true;
        }


        public override bool GenerateHardwareScripts()
        {
            HardwareScript oScript = HardwareScripts.NewScript("test");

            return true;
        }

    }
}
